package com.ibeeking.found.uaa.cp.service.impl;

import com.ibeeking.found.auth.api.common.dto.LoginCpUserDTO;
import com.ibeeking.found.auth.api.common.query.LoginAuthQuery;
import com.ibeeking.found.auth.api.feign.CpLoginClient;
import com.ibeeking.found.common.config.feign.MsgFeignClient;
import com.ibeeking.found.common.enums.EmployeeStatusEnum;
import com.ibeeking.found.common.enums.LoginModeEnum;
import com.ibeeking.found.common.enums.LoginRoleEnum;
import com.ibeeking.found.uaa.cp.model.CpAuthModel;
import com.ibeeking.found.uaa.cp.model.CpUserDetails;
import com.ibeeking.found.uaa.cp.model.SmsCodeModel;
import com.ibeeking.found.uaa.cp.service.ICpUserDetailsService;
import com.ibeeking.nematos.constants.enums.LogConstant;
import com.ibeeking.nematos.exception.AuthorizationException;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.http.HttpStatus;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author ibeeking
 */
@Service
public class CpUserDetailsServiceImpl implements ICpUserDetailsService {

    @Resource
    private CpLoginClient cpLoginClient;

    @Resource
    private MsgFeignClient msgClient;

    @Override
    public CpUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String tenantId = ThreadContext.get(LogConstant.TENANT_ID);
        if (StringUtils.isBlank(tenantId)) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "tenantId空，请选择租户后登录");
        }
        LoginAuthQuery query = new LoginAuthQuery();
        query.setLoginMode(LoginModeEnum.MOBILE.getCode());
        query.setMobile(username);
        ResponseResult<LoginCpUserDTO> responseResult = cpLoginClient.queryLoginCpUser(query);
        if (null == responseResult || null == responseResult.getData()) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "用户名或密码错误");
        }
        CpUserDetails userDetails =  TransferCpUserCpUserDetail(tenantId, responseResult.getData());
        return userDetails;
    }

    @Override
    public CpUserDetails loadUserByPhoneAndSmsCode(SmsCodeModel smsCodeModel) {
        String tenantId = ThreadContext.get(LogConstant.TENANT_ID);
        if (StringUtils.isBlank(tenantId)) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "请选择应用后登录");
        }
        if (StringUtils.isBlank(smsCodeModel.getMobile())) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "手机号不能为空");
        }
        if (StringUtils.isBlank(smsCodeModel.getCode())) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "手机验证码不能为空");
        }
        if (StringUtils.isBlank(smsCodeModel.getKey())) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "验证码标识不能为空");
        }
        ResponseResult<Boolean> responseResult = msgClient.checkVerificationCode(smsCodeModel.getKey(), smsCodeModel.getMobile(), smsCodeModel.getCode());
        if (null == responseResult || !responseResult.getData()) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "验证码错误或已过期");
        }
        LoginAuthQuery query = new LoginAuthQuery();
        query.setLoginMode(LoginModeEnum.MOBILE.getCode());
        query.setMobile(smsCodeModel.getMobile());
        ResponseResult<LoginCpUserDTO> result = cpLoginClient.queryLoginCpUser(query);
        if (null == result || null == result.getData()) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "用户不存在，请注册后再试");
        }
        CpUserDetails userDetails =  TransferCpUserCpUserDetail(tenantId, result.getData());
        return userDetails;
    }

    @Override
    public CpUserDetails cpAuthLogin(CpAuthModel cpModel) {
        String tenantId = ThreadContext.get(LogConstant.TENANT_ID);
        if (StringUtils.isBlank(tenantId)) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "tenantId空，请选择租户后登录");
        }
        if (StringUtils.isBlank(cpModel.getOpenId())) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "登录用户名必填");
        }
        ResponseResult<LoginCpUserDTO> responseResult = cpLoginClient.queryUserByOpenId(cpModel.getOpenId());
        if (null == responseResult || null == responseResult.getData()) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "查询会员信息失败");
        }
        return TransferCpUserCpUserDetail(tenantId, responseResult.getData());
    }

    /***
     * 封装查询登录用户
     * @param loginUserInfo 参数
     * @return
     */
    private CpUserDetails TransferCpUserCpUserDetail(String tenantId, LoginCpUserDTO loginUserInfo) {
        if (null == loginUserInfo) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "企业小程序用户不存在");
        }
        if (!EmployeeStatusEnum.IS_ACTIVED.getCode().equals(loginUserInfo.getPublishStatus())) {
            throw new AuthorizationException(HttpStatus.UNAUTHORIZED.value(), "当前企业应用用户禁止登陆");
        }
        CpUserDetails cpUserDetails = new CpUserDetails();
        cpUserDetails.setId(loginUserInfo.getId());
        cpUserDetails.setTenantId(tenantId);
        cpUserDetails.setIndustry(loginUserInfo.getIndustry());
        cpUserDetails.setUserCode(loginUserInfo.getUserCode());
        cpUserDetails.setPassword(loginUserInfo.getPassword());
        cpUserDetails.setName(loginUserInfo.getName());
        cpUserDetails.setMobile(loginUserInfo.getMobile());
        cpUserDetails.setEmail(loginUserInfo.getEmail());
        cpUserDetails.setWxUserId(loginUserInfo.getWxUserId());
        cpUserDetails.setDingUserId(loginUserInfo.getDingUserId());
        cpUserDetails.setRegister(StringUtils.isEmpty(loginUserInfo.getWxUserId())?false:true);

        List<SimpleGrantedAuthority> roles = new ArrayList<>();
        roles.add(new SimpleGrantedAuthority(LoginRoleEnum.WX_CP.name()));
        roles.add(new SimpleGrantedAuthority(LoginRoleEnum.WX_CP.name()));
        cpUserDetails.setRoles(roles);
        return cpUserDetails;
    }
}
